package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.acct.facade.request.VirtAcctSingleAdjustRequest;
import cc.rengu.igas.acct.facade.request.VirtAcctTransStatusQueryRequest;
import cc.rengu.igas.acct.facade.response.VirtAcctSingleAdjustResponse;
import cc.rengu.igas.acct.facade.result.Result;
import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.dao.BspsMchntAcctInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsMchntFeeInfoMapper;
import cc.rengu.igas.bsps.common.dao.RoleAcctInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntAcctInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntFeeInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.RoleAcctInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntAcctInfo;
import cc.rengu.igas.bsps.common.entity.MchntFeeInfo;
import cc.rengu.igas.bsps.common.entity.RoleAcctInfo;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.realize.UserPermissionCheckService;
import cc.rengu.igas.bsps.core.realize.impl.UserPermissionCheckServiceImpl;
import cc.rengu.igas.bsps.core.service.base.PayService;
import cc.rengu.igas.bsps.facade.base.Header;
import cc.rengu.igas.bsps.facade.request.VirtualAcctRechargeRequest;
import cc.rengu.igas.bsps.facade.response.VirtualAcctRechargeResponse;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 虚拟账户充值.
 */
public class VirtualAcctRechargeService extends PayService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        VirtualAcctRechargeRequest virtualAcctRechargeRequest = new VirtualAcctRechargeRequest();
        ConvertUtil.convertOutput(virtualAcctRechargeRequest);
        return virtualAcctRechargeRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        VirtualAcctRechargeRequest virtualAcctRechargeRequest = (VirtualAcctRechargeRequest) request;
        String instId = virtualAcctRechargeRequest.getHeader().getInstId();
        String mchntNo = virtualAcctRechargeRequest.getMchntNo();
        String orderAmt = virtualAcctRechargeRequest.getOrderAmt();
        String traceNo = virtualAcctRechargeRequest.getHeader().getTraceNo();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String payAcctNo = virtualAcctRechargeRequest.getPayAcctNo();
        String mainMchntNo = null;
        String chainMchntFlag = AppParamConstant.NO;
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList();
        if (CollectionUtils.isEmpty(channelCallCfgList)) {
            rglog.error("通道服务调用配置表无数据！,instId:<{}>,traceNo:<{}>,",
                    virtualAcctRechargeRequest.getHeader().getInstId(), virtualAcctRechargeRequest.getHeader().getTraceNo());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        /*充值金额校验*/
        orderAmt = AmountUtil.checkAmt(orderAmt, 2, false);
        BizResponse<VirtualAcctRechargeResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        VirtualAcctRechargeResponse virtualAcctRechargeResponse = new VirtualAcctRechargeResponse();

        /*检查会话*/
        UserPermissionCheckService userPermissionCheckService = new UserPermissionCheckServiceImpl();
        UserSessionInfo userSessionInfo = userPermissionCheckService.checkUserLoginSessionStatus(instId,
                virtualAcctRechargeRequest.getHeader().getSession(), virtualAcctRechargeRequest.getUserId());

        /* 校验短信验证码 */
        if (userSessionInfo.getSmsVerifySeqNum().equals(virtualAcctRechargeRequest.getSmsAuthId())) {
            SmsService smsService = new SmsServiceImpl();
            smsService.verifySmsCode(instId, SmsTypeEnum.ACCT_RECHARGE.getSmsType(),
                    virtualAcctRechargeRequest.getSmsCode(), virtualAcctRechargeRequest.getSmsAuthId());
        } else {
            throw new BizException(OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespCode(), OltpRpcdEnum.VERIFY_SMS_CODE_ERROR.getRespDesc());
        }

        Map<String, String> sensitiveMap = userSessionInfo.getSensitiveMap();
        if (CollectionUtils.isEmpty(sensitiveMap)) {
            rglog.error("结算账户信息获取失败");
            throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        } else {
            payAcctNo = SensitiveDataUtil.reducition(payAcctNo, sensitiveMap);
            rglog.info("脱敏结算账户信息acctNo:" + payAcctNo);
        }

        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntNo);
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        /*判断是否独立维护资料的门店*/
        if ("11".equals(mchntInfo.getMchntType()) && !AppParamConstant.YES.equals(mchntInfo.getIndependentDataFlag())) {
            mainMchntNo = mchntInfo.getChainMchntNo();
            chainMchntFlag = AppParamConstant.YES;
        } else {
            mainMchntNo = mchntInfo.getMchntNo();
        }

        /*判断是否为特殊费率商户*/
        BspsMchntFeeInfoMapper mchntFeeInfoMapper = new BspsMchntFeeInfoMapperImpl();
        List<MchntFeeInfo> mchntFeeInfoList = mchntFeeInfoMapper.selectFormalMchntFeeInfoByMchntNo(instId, mainMchntNo, null);
        if (!CollectionUtils.isEmpty(mchntFeeInfoList)) {
            mchntFeeInfoList = mchntFeeInfoList.stream().filter(mchntFeeInfo -> "0".equals(mchntFeeInfo.getFeeInputMode())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(mchntFeeInfoList)) {
                rglog.error("商户为特殊费率商户,不允许进行充值");
                throw new BizException(RespCodeEnum.SPECIAL_FEE_CANNOT_RECHARGE.getRespCode(), RespCodeEnum.SPECIAL_FEE_CANNOT_RECHARGE.getRespDesc());
            }
        }

        /*查询商户结算账户信息,付款账户必须商户结算账户 */
        BspsMchntAcctInfoMapper bspsMchntAcctInfoMapper = new BspsMchntAcctInfoMapperImpl();
        List<MchntAcctInfo> mchntAcctInfoList = bspsMchntAcctInfoMapper.selectBspsMchntAcctInfoByMchntNo(instId, mainMchntNo);
        if (null == mchntAcctInfoList) {
            rglog.error("商户结算账户信息查询失败！拒绝充值请求！userId:<{}>，前端流水号：<{}>,mchntNo:<{}>", virtualAcctRechargeRequest.getUserId(), traceNo, mainMchntNo);
            throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }
        String finalPayAcctNo = payAcctNo;
        Predicate<MchntAcctInfo> acctNo = p -> finalPayAcctNo.equals(p.getSettleAcctNo());
        Predicate<MchntAcctInfo> status = p -> AppParamConstant.YES.equals(p.getRecordStatus());
        mchntAcctInfoList = mchntAcctInfoList.stream().filter(acctNo.and(status)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(mchntAcctInfoList)) {
            rglog.error("被查询账户<{}>在商户结算账户信息列表查无记录！拒绝余额请求！mchntNo:<{}>", payAcctNo, mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }

        /*检查当天累计限额，上限一千*/
        checkAmtLimit(virtualAcctRechargeRequest);

        /*  获取机构内部户 商户结算账户->本行渠道户  */
        RoleAcctInfoMapper roleAcctInfoMapper = new RoleAcctInfoMapperImpl();
        RoleAcctInfo roleAcctInfo = roleAcctInfoMapper.selectBankRoleAcctInfoBySettleAcctId(virtualAcctRechargeRequest.getHeader().getInstId(), SettleAcctTypeEnum.BANK_PAYCHNL_SUBJECT.getSettleAcct());
        if (null == roleAcctInfo) {
            rglog.error("机构内部户信息查询失败！拒绝充值请求！userId:<{}>，sysSeqNum：<{}>,mchntNo:<{}>", virtualAcctRechargeRequest.getUserId(), sysSeqNum, mchntNo);
            throw new BizException(RespCodeEnum.INST_SETTLE_ACCT_NOT_FOUND.getRespCode(), RespCodeEnum.INST_SETTLE_ACCT_NOT_FOUND.getRespDesc());
        }

        //初始化用户订单信息
        UserOrderInfo userOrderInfo = initUserOrderInfo(virtualAcctRechargeRequest, orderAmt, sysSeqNum);
        //初始化商户订单信息
        MchntOrderInfo mchntOrderInfo = initMchntOrderInfo(virtualAcctRechargeRequest);
        if (chainMchntFlag.equals(AppParamConstant.YES)) {
            mchntOrderInfo.setChainMchntNo(mainMchntNo);
        }
        //初始化 esb-支付订单信息
        List<ChannelCallCfg> channelCallCfgListEsb = channelCallCfgList.stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ESB.getChannelType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(channelCallCfgListEsb)) {
            rglog.error("通道服务调用配置表无数据！,instId:<{}>,traceNo:<{}>,",
                    virtualAcctRechargeRequest.getHeader().getInstId(), virtualAcctRechargeRequest.getHeader().getTraceNo());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        List<ChannelCallCfg> channelCallCfgListAcct = channelCallCfgList.stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ACCT.getChannelType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(channelCallCfgListAcct)) {
            rglog.error("通道服务调用配置表无数据！,instId:<{}>,traceNo:<{}>,",
                    virtualAcctRechargeRequest.getHeader().getInstId(), virtualAcctRechargeRequest.getHeader().getTraceNo());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        PayOrderInfo esbPayOrderInfo = initPayOrderInfo(virtualAcctRechargeRequest, channelCallCfgListEsb.get(0));
        esbPayOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(virtualAcctRechargeRequest.getHeader().getInstId()));
        esbPayOrderInfo.setPayerAcctInfo(payAcctNo);
        esbPayOrderInfo.setPayeeAcctInfo(roleAcctInfo.getActualAcct());
        esbPayOrderInfo.setTransBatchNo("0000");
        //新增订单信息
        OrderService orderService = new OrderServiceImpl();
        boolean dbResult = orderService.registerOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), esbPayOrderInfo);
        if (!dbResult) {
            rglog.error("新增用户订单，商户订单，支付订单失败，提现交易失败！instId:<{}>，sysSeqNum：<{}>", instId, sysSeqNum);
            throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
        }

        /* TODO 调用esb核心接口扣款 */
        // （1） 调用核心扣款接口，分析调用结果
        // （2）  通讯级失败，更新订单为失败updateFailOrderStatus, 抛出异常
        // (3) 业务超时,更新订单表状态为失败updateFailOrderStatus, 调用核心冲正接口coreRevsal,抛出异常
        // (4) 交易成功,更新支付订单esbPayOrderInfo为成功,程序继续执行


        /* 新增 虚拟账户记账-支付订单 */
        PayOrderInfo acctPayOrderInfo = initPayOrderInfo(virtualAcctRechargeRequest, channelCallCfgListAcct.get(0));
        acctPayOrderInfo.setChannelReconKey(sysSeqNum + channelCallCfgListAcct.get(0).getCallIndex());
        dbResult = orderService.registerOrderInfo(null, null, acctPayOrderInfo);
        if (!dbResult) {
            /*异步调用记账冲正*/
            coreRevsal();
            rglog.error("新增虚拟账户支付订单失败，充值交易失败！instId:<{}>，sysSeqNum：<{}>", instId, sysSeqNum);
            throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
        }

        /*调用虚拟账户记账*/
        VirtAcctSingleAdjustResponse response = virtAcctSingleAdjust(virtualAcctRechargeRequest, userOrderInfo, mchntOrderInfo, acctPayOrderInfo, channelCallCfgListAcct.get(0), mainMchntNo);
        virtualAcctRechargeResponse.setAvailableBalance(response.getAfterAvailableBalance());
        virtualAcctRechargeResponse.setAcctBalance(response.getAfterBalance());
        virtualAcctRechargeResponse.setFreezeBalance(response.getAfterFreezeBalance());
        virtualAcctRechargeResponse.setSysSeqNum(sysSeqNum);
        bizResponse.setResult(virtualAcctRechargeResponse);
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        /*异步推送充值结果*/

        return bizResponse;
    }

    private VirtAcctSingleAdjustResponse virtAcctSingleAdjust(VirtualAcctRechargeRequest virtualAcctRechargeRequest, UserOrderInfo userOrderInfo,
                                                              MchntOrderInfo mchntOrderInfo, PayOrderInfo acctPayOrderInfo, ChannelCallCfg channelCallCfg, String mchntNo) throws Exception {

        OrderService orderService = new OrderServiceImpl();

        VirtAcctSingleAdjustRequest request = new VirtAcctSingleAdjustRequest();
        cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
        BeanUtil.beanCopy(virtualAcctRechargeRequest.getHeader(), header);
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setTraceNo(acctPayOrderInfo.getChannelReconKey());
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setChanlId(BspsAppParamConstant.BSP_SYS_ID);
        request.setHeader(header);
        request.setAcctType("00");
        request.setDebitCreditFlag("C");
        //userType : 00-商户  01-会员 02-营销
        request.setUserType("00");
        request.setUserId(mchntNo);
        request.setTransAmt(mchntOrderInfo.getOrderAmt());
        DubboService dubboService = new DubboServiceImpl();
        Result<VirtAcctSingleAdjustResponse> responseResult = (Result<VirtAcctSingleAdjustResponse>) dubboService.callDubboService("virtAcctService", "virtAcctSingleAdjust", request);
        if (null == responseResult) {
            updateFailOrderStatus(userOrderInfo, mchntOrderInfo, acctPayOrderInfo);
            /*异步调用核心冲正*/
            coreRevsal();
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        } else if (OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode().equals(responseResult.getResult().getRespCode())) {
            /*异步调用虚拟账户查询*/
            virtAcctTransStatusQuery(request, acctPayOrderInfo);
            throw new BizException(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode(), OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
        }
        if (!responseResult.isSuccess() || (!BspsAppParamConstant.DUBBO_SUCCESS.equals(responseResult.getResult().getRespCode()) &&
                !OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode().equals(responseResult.getResult().getRespCode()))) {
            rglog.error("调用dubbo服务virtAcctSingleAdjust失败");
            updateFailOrderStatus(userOrderInfo, mchntOrderInfo, acctPayOrderInfo);
            /*异步调用核心冲正*/
            coreRevsal();
            if (!responseResult.isSuccess()) {
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            } else {
                throw new BizException(responseResult.getResult().getRespCode(), responseResult.getResult().getRespDesc());
            }
        } else if (OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode().equals(responseResult.getResult().getRespCode())) {
            /*异步调用虚拟账户查询*/
            virtAcctTransStatusQuery(request, acctPayOrderInfo);
            //todo 虚拟账户状态查询接口
            throw new BizException(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode(), OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
        } else {
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

            acctPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            acctPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            acctPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), acctPayOrderInfo)) {
                rglog.error("更新订单表状态失败");
                /*返回结果未知，让前端发起查询*/
                throw new BizException(OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespCode(), OltpRpcdEnum.BIZ_PROCESS_TIMEOUT.getRespDesc());
            }
        }
        return responseResult.getResult();
    }


    private PayOrderInfo initPayOrderInfo(VirtualAcctRechargeRequest virtualAcctRechargeRequest, ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        ConvertUtil.convertOutput(payOrderInfo);
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setMchntOrderId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setOrderAmt(AmountUtil.multiplication(virtualAcctRechargeRequest.getOrderAmt(), "1", 2));
        payOrderInfo.setRealPayAmt(AmountUtil.multiplication(virtualAcctRechargeRequest.getOrderAmt(), "1", 2));
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId()); //交易通道标识
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setDstChannelType("");
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType()); //银行卡支付
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return payOrderInfo;
    }

    private MchntOrderInfo initMchntOrderInfo(VirtualAcctRechargeRequest virtualAcctRechargeRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MchntOrderInfo mchntOrderInfo = new MchntOrderInfo();
        ConvertUtil.convertOutput(mchntOrderInfo);
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(virtualAcctRechargeRequest.getHeader().getInstId(), virtualAcctRechargeRequest.getMchntNo());
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", virtualAcctRechargeRequest.getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        //基础公共
        mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        mchntOrderInfo.setSysSeqNum(sysSeqNum);
        mchntOrderInfo.setMchntOrderId(sysSeqNum);
        mchntOrderInfo.setAcqInstCode(mchntInfo.getSignInstId());
        mchntOrderInfo.setIndustryType(mchntInfo.getIndustryType());
        mchntOrderInfo.setMchntNo(virtualAcctRechargeRequest.getMchntNo());
        mchntOrderInfo.setMchntName(mchntInfo.getMchntName());
        mchntOrderInfo.setOrderAmt(AmountUtil.multiplication(virtualAcctRechargeRequest.getOrderAmt(), "1", 2));
        mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
        mchntOrderInfo.setRealSettleAmt(AmountUtil.multiplication(virtualAcctRechargeRequest.getOrderAmt(), "1", 2));
        mchntOrderInfo.setMchntSettleAmt(AmountUtil.multiplication(virtualAcctRechargeRequest.getOrderAmt(), "1", 2));
        mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        return mchntOrderInfo;
    }

    /**
     * 初始化用户订单信息
     *
     * @param virtualAcctRechargeRequest 请求
     * @param orderAmt                   订单金额
     * @param sysSeqNum                  系统标识号
     * @return 用户订单信息
     * @throws Exception 异常
     */
    private UserOrderInfo initUserOrderInfo(VirtualAcctRechargeRequest virtualAcctRechargeRequest, String orderAmt, String sysSeqNum) throws Exception {
        Header header = virtualAcctRechargeRequest.getHeader();
        UserOrderInfo userOrderInfo = new UserOrderInfo();
        ConvertUtil.convertOutput(userOrderInfo);
        userOrderInfo.setOrderAmt(orderAmt);
        userOrderInfo.setUserId(virtualAcctRechargeRequest.getUserId());
        userOrderInfo.setSysSeqNum(sysSeqNum);
        userOrderInfo.setMsgSrcId(header.getSrcSysId());
        userOrderInfo.setTransChannelId(header.getChanlId());
        userOrderInfo.setMchntOrderId(sysSeqNum);
        userOrderInfo.setFrontSeqNum(header.getTraceNo());
        Date date = new Date();
        String currentDateTime = DateUtil.getDateByTimeStamp(date.getTime(), "yyyyMMddhhmmss");
        userOrderInfo.setOrderCreateTime(currentDateTime);
        long expiryTime = date.getTime() + BspsAppParamConstant.ORDER_EXPIRY_TIME;
        String orderExpiryTime = DateUtil.getDateByTimeStamp(expiryTime, "yyyyMMddhhmmss");
        userOrderInfo.setOrderExpiryTime(orderExpiryTime);
        userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setCreateTime(currentDateTime);
        rglog.debug(JSONObject.toJSONString(userOrderInfo));
        return userOrderInfo;
    }

    /*异步查询虚拟账户状态*/
    void virtAcctTransStatusQuery(VirtAcctSingleAdjustRequest request, PayOrderInfo payOrderInfo) {
        DubboService dubboService = new DubboServiceImpl();
        try {
            cc.rengu.igas.acct.facade.base.Header header = request.getHeader();
            VirtAcctTransStatusQueryRequest virtAcctTransStatusQueryRequest = new VirtAcctTransStatusQueryRequest();
            virtAcctTransStatusQueryRequest.setUserType("00");
            virtAcctTransStatusQueryRequest.setUserId(request.getUserId());
            virtAcctTransStatusQueryRequest.setAcctType("00");  //虚拟账户
            virtAcctTransStatusQueryRequest.setTransSeqNum(payOrderInfo.getChannelReconKey());
            header.setTxnNum("T00AT004");
            header.setTraceNo(payOrderInfo.getSysSeqNum() + String.valueOf(Integer.parseInt(payOrderInfo.getDstCallIndex()) + 1));
            virtAcctTransStatusQueryRequest.setHeader(header);
            int iReturnCode = dubboService.asynCallDubboService("virtAcctService", "virtAcctTransStatusQuery", virtAcctTransStatusQueryRequest, "AsynVirtAcctTransStatusQueryService");
        } catch (Exception e) {
            rglog.error(e.getMessage());

        }

    }


    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        VirtualAcctRechargeResponse virtualAcctRechargeResponse = (VirtualAcctRechargeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(virtualAcctRechargeResponse);
    }

    void checkAmtLimit(VirtualAcctRechargeRequest virtualAcctRechargeRequest) throws Exception {
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoListMchnt = mchntOrderInfoMapper.selectMchntOrderInfoByMchntNo(virtualAcctRechargeRequest.getHeader().getInstId(),
                virtualAcctRechargeRequest.getMchntNo(), DateUtil.getCurrentDate(), DateUtil.getCurrentDate());
        if (mchntOrderInfoListMchnt != null && !mchntOrderInfoListMchnt.isEmpty()) {
            Predicate<MchntOrderInfo> sucStat = p -> TransStatusEnum.TRANS_SUCC.getStatus().equals(p.getTransStatus());
            Predicate<MchntOrderInfo> txnNum = p -> virtualAcctRechargeRequest.getHeader().getTxnNum().equals(p.getTxnNum());
            mchntOrderInfoListMchnt = mchntOrderInfoListMchnt.stream().filter(sucStat.and(txnNum)).collect(Collectors.toList());
            if (mchntOrderInfoListMchnt == null || mchntOrderInfoListMchnt.size() == 0) {
                rglog.error("商户当天未发生过成功充值");
                return;
            }
            String totalTransAmt = "0.00";
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoListMchnt) {
                totalTransAmt = AmountUtil.addition(totalTransAmt, mchntOrderInfo.getOrderAmt());
            }
            if (AmountUtil.compare(AmountUtil.addition(totalTransAmt, virtualAcctRechargeRequest.getOrderAmt()), BspsAppParamConstant.RECHARGE_TOTAL_AMT) == 1) {
                rglog.error("当天成功充值总金额<{}>+本次退款金额<{}>大于当天累计充值金额上限<{}>，不允许充值",
                        totalTransAmt, virtualAcctRechargeRequest.getOrderAmt(), BspsAppParamConstant.RECHARGE_TOTAL_AMT);
                throw new BizException(RespCodeEnum.WITHDRAWAL_AMT_OVER_LIMIT.getRespCode(), RespCodeEnum.WITHDRAWAL_AMT_OVER_LIMIT.getRespDesc());
            }
        }
    }

    Boolean updateFailOrderStatus(UserOrderInfo userOrderInfo, MchntOrderInfo mchntOrderInfo, PayOrderInfo payOrderInfo) throws Exception {
        OrderService orderService = new OrderServiceImpl();
        /*更新订单表状态为失败*/
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
        payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfo)) {
            rglog.error("更新订单表状态失败");
            return false;
        }
        return true;
    }

    /* TODO 核心记账冲正 */
    void coreRevsal() {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
//            CoreGeneralAcctTransferRequest coreGeneralAcctTcransferRequest = (CoreGeneralAcctTransferRequest)
//                    xmlTreeUtil.getXmlTreeObjectValue("coreGeneralAcctTcransferRequest",CoreGeneralAcctTransferRequest.class);
//            cc.rengu.igas.channel.esb.facade.base.Header esbHeader = coreGeneralAcctTcransferRequest.getHeader();
//            CoreGeneralAcctRevsalRequest coreGeneralAcctRevsalRequest = new CoreGeneralAcctRevsalRequest();
//            coreGeneralAcctRevsalRequest.setOrigTraceNo(esbHeader.getTraceNo());
//            coreGeneralAcctRevsalRequest.setOrigTransDate(esbHeader.getTransDate());
//            coreGeneralAcctRevsalRequest.setCardNo(coreGeneralAcctTcransferRequest.getChnlPayInfo().getPayeeAcctInfo());
//            coreGeneralAcctRevsalRequest.setTransAmt(coreGeneralAcctTcransferRequest.getChnlPayInfo().getRealPayAmt());
//            coreGeneralAcctRevsalRequest.setGlobalTraceNum(GlobalEsbUtil.getGlobalTraceNumber());
//            coreGeneralAcctRevsalRequest.setGlobalPathNum(GlobalEsbUtil.getGlobalPathNumber());
//            esbHeader.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(esbHeader.getInstId()));
//            esbHeader.setTxnNum("00010000999800");
//            coreGeneralAcctRevsalRequest.setHeader(esbHeader);
//            DubboService dubboService = new DubboServiceImpl();
//            int iReturnCode = dubboService.asynCallDubboService("coreEsbService","coreGeneralAcctRevsal",coreGeneralAcctRevsalRequest,"AsynCoreRevsalService");
//            if(iReturnCode != 0){
//                rglog.error("核心记账冲正注册失败！");
//            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
        }
    }
}
